package org.dxy.domain.handler.workorder;

import com.google.common.eventbus.EventBus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.domain.port.IEventRepository;
import org.dxy.domain.port.CommandHandler;
import org.dxy.domain.port.repository.IWorkOrderRepository;
import org.dxy.domain.command.workorder.UpdateWorkOrderCommand;
import org.dxy.domain.event.DomainEvent;
import org.dxy.domain.model.aggregate.WorkOrder;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.List;

/**
 * 更新工单命令处理器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class UpdateWorkOrderCommandHandler implements CommandHandler<UpdateWorkOrderCommand, Void> {

    private final IWorkOrderRepository workOrderRepository;
    private final EventBus eventBus;
    private final IEventRepository eventRepository;
    
    @Transactional
    @Override
    public CommandResult<Void> handle(UpdateWorkOrderCommand command) {
        // 1. 查找工单
        WorkOrder workOrder = workOrderRepository.findById(command.workOrderId());
        if (workOrder == null) {
            return CommandResult.fail("工单不存在");
        }
        
        // 2. 检查工单状态是否允许更新
        if (!workOrder.canUpdate()) {
            return CommandResult.fail("当前工单状态不允许更新");
        }
        
        // 3. 检查工单编码唯一性（如果编码发生变化）
        if (!workOrder.getWorkOrderCode().equals(command.workOrderCode()) &&
            workOrderRepository.existsByCode(command.workOrderCode())) {
            return CommandResult.fail("工单编码已存在");
        }
        
        // 4. 根据具体变更内容调用相应的细粒度方法
        // 检查并更新计划数量
        if (command.plannedQuantity() != null && 
            !command.plannedQuantity().equals(workOrder.getPlannedQuantity())) {
            workOrder.changeQuantity(command.plannedQuantity());
        }
        
        // 检查并更新产线分配
        if (command.productionLineId() != null && 
            !command.productionLineId().equals(workOrder.getProductionLineId())) {
            workOrder.changeProductionLine(command.productionLineId());
        }
        
        // 检查并更新工艺路线
        if (command.routeId() != null && 
            !command.routeId().equals(workOrder.getRouteId())) {
            workOrder.changeRoute(command.routeId());
        }
        
        // 如果没有任何变更，直接返回
        if (!workOrder.hasDomainEvents()) {
            return CommandResult.success("工单信息无变更");
        }
        
        // 5. 保存聚合根
        workOrderRepository.save(workOrder);

        List<DomainEvent> events = workOrder.getDomainEvents();
        // 6. 保存事件到事件存储
        eventRepository.saveEvents(events);
        
        // 7. 注册事务提交后的事件发布回调
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                events.forEach(eventBus::post);
            }
        });

        List<Long> eventIds = events.stream().map(DomainEvent::eventId).toList();
        eventRepository.markEventsPublished(eventIds);
        
        // 8. 清理事件
        workOrder.clearDomainEvents();
        
        log.info("工单更新成功, command={}", command);
        return CommandResult.success("工单更新成功");
    }
}